﻿/*  Copyright 2012 PerceiveIT Limited
 *  This file is part of the Scryber library.
 *
 *  You can redistribute Scryber and/or modify 
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  Scryber is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 * 
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with Scryber source code in the COPYING.txt file.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Scryber.Components;
using Scryber.Styles;
using Scryber.Drawing;
using Scryber.Native;
using Scryber.Modifications.Parsing;

namespace Scryber.Modifications
{
    public abstract class PDFModifyPageBase : PDFPage
    {
        #region public int Index {get;set;}

        /// <summary>
        /// Gets or sets the index of the existing pages this content will be updating.
        /// </summary>
        [PDFAttribute("page-index", Const.PDFModificationsNamespace)]
        public int ModifyPageIndex
        {
            get { return this.Style.PageModifications.PageStartIndex; }
            set { this.Style.PageModifications.PageStartIndex = value; }
        }

        #endregion

        /// <summary>
        /// Gets or sets the number of existing pages this content will be updating
        /// </summary>
        [PDFAttribute("page-count", Const.PDFModificationsNamespace)]
        public int ModifyPageCount
        {
            get { return this.Style.PageModifications.PageCount; }
            set { this.Style.PageModifications.PageCount = value; }
        }

        #region public ModifiedContentAction OriginalContent {get;set;}

        /// <summary>
        /// Gets or sets the content retention options for the page being updated.
        /// </summary>
        [PDFAttribute("content-action", Const.PDFModificationsNamespace)]
        public ModifiedContentAction ModifyContentAction
        {
            get { return this.Style.PageModifications.ContentAction; }
            set { this.Style.PageModifications.ContentAction = value; }
        }

        #endregion

        


        public PDFModifyPageBase(PDFObjectType type)
            : base(type)
        {
        }

        public override PDFPageSize GetPageSize(PDFStyle style)
        {
            PDFPageSize pgsize = base.GetPageSize(style);

            PDFFile source = this.Document.OriginalSourceFile;
            if (source != null)
            {
                int index = style.GetValue(PDFStyleKeys.ModifyPageStartIndexKey, this.PageIndex);
                
                if (index < source.PageRefs.Length)
                {
                    PDFObjectRef pgRef = this.Document.OriginalSourceFile.PageRefs[index];

                    PDFParsedPage pgdata = this.Document.OriginalSourceFile.GetPage(pgRef);
                    PDFRect bounds = this.GetRequiredPageBounds(pgdata, pgsize.Size, style);
                    pgsize.Size = bounds.Size;
                }
                
            }
            return pgsize;
        }


        public PDFRect GetRequiredPageBounds(PDFParsedPage pgdata, PDFSize orig, PDFStyle defined)
        {
            PDFRect full = new PDFRect(PDFPoint.Empty, orig);
            PDFStyleValue<PDFUnit> width, height;
            PDFStyleValue<PaperSize> size;

            
            defined.CreatePageSize();
            //check if the page has a size in its style, or 
            if (defined.TryGetValue(PDFStyleKeys.PagePaperSizeKey,out size) || 
                        (defined.TryGetValue(PDFStyleKeys.PageWidthKey,out width) && defined.TryGetValue(PDFStyleKeys.PageHeightKey,out height)))
            {
                //We have an explicit size So let's use that instead.
                PDFPageSize pgSize = defined.CreatePageSize();
                full.Size = new PDFSize(pgSize.Width, pgSize.Height);
            }
            else if (null != pgdata.MediaBox)
            {
                full = pgdata.GetPageBounds();
                defined.SetValue(PDFStyleKeys.PageWidthKey, full.Width);
                defined.SetValue(PDFStyleKeys.PageHeightKey,full.Height);
            }

            return full;
        }

        protected override PDFStyle GetBaseStyle()
        {
            PDFStyle style = base.GetBaseStyle();
            PDFModifyPageStyle updateStyle = style.PageModifications;
            ApplyUpdateStyleToBase(updateStyle);

            return style;
        }

        protected abstract void ApplyUpdateStyleToBase(PDFModifyPageStyle updateStyle);


        public override IPDFLayoutEngine GetEngine(IPDFLayoutEngine parent, PDFLayoutContext context, PDFStyle style)
        {
            context.TraceLog.Add(TraceLevel.Debug, "Modifications", "Instantiating the ModifyPageLayoutEngine");
            return new Layout.ModifyPageLayoutEngine(this, parent);
        }
        
    }
}
